/**
 * @file battery_error.c
 * @brief 
 * @author Tome (baojian.liu-a1105@aqara.com)
 * @date 2021-04-22
 */
 
 
 
/****************************************************************************************************************************** 
                                                            const
*******************************************************************************************************************************/




#define BRAIN_WARN_LED_INTERVAL_MS     20000







/****************************************************************************************************************************** 
                                                            typedef
*******************************************************************************************************************************/













/****************************************************************************************************************************** 
                                                            MICRO
*******************************************************************************************************************************/


#define U32_FF      0xFFFFFFFFu




/****************************************************************************************************************************** 
                                                            declearation
*******************************************************************************************************************************/











/****************************************************************************************************************************** 
                                                            defination
*******************************************************************************************************************************/

uint32 g32_usb_insert_time = U32_FF;
uint32 g32_usb_remove_time = U32_FF;
//uint8  g8_usb_insert_protect = 0;



// 
/*********************************************************************
 * @fn      warn_code_clear_handler
 *
 * @brief   usb insert and remove timeout protect
 *
 * @param   void
 *
 * @return  void
 */
void user_warn_usb_remove_protect(void)
{
    uint32 time;
    time = osal_getClock();
    
    time -= g32_usb_remove_time;
    
    if ( time >= 1800 ) // 1800 / 60 = 30 min
    {
        g32_usb_insert_time = U32_FF;
        return;
    }
    osal_start_timerEx(Brain_TaskID, TASK_BRAIN_EVT_USB_OUT_DELAY, 30000);  // 30 second
}



/*********************************************************************
 * @fn      warn_code_clear_handler
 *
 * @brief   TASK_BRAIN_EVT_WARN_CLEAR handler
 *
 * @param   void
 *
 * @return  void
 */
void warn_code_clear_handler(void)
{
    *d1_attr_state = 0;
    osal_stop_timerEx(Brain_TaskID, TASK_BRAIN_EVT_WARN_LED);
    
}


/*********************************************************************
 * @fn      warn_code_led_handler
 *
 * @brief   TASK_BRAIN_EVT_WARN_LED handler
 *
 * @param   void
 *
 * @return  void
 */
void warn_code_led_handler(void)
{
    //static uint32 warn_code = *d1_attr_state;
    //static uint32 warn_mask = 0x1;
    
    uint32 mask = 0x01;
    uint8 code = 0,i = 0;
    
    if (*d1_attr_state == 0)return;
    
    for ( i = 0; i < 32; i++){  
        if ( mask & *d1_attr_state){ code = i ; break;}
        mask <<= 1;
    }
    BRAINLOG("[XD]%d",code);
    
    // led...
    task_led_err_code(code);
    
    
    osal_start_timerEx(Brain_TaskID, TASK_BRAIN_EVT_WARN_LED, BRAIN_WARN_LED_INTERVAL_MS);
    
    
}



/*********************************************************************
 * @fn      task_brain_set_warn_code
 *
 * @brief   send error code, used for collection error 
 *
 * @param   code , warn code;
 *
 * @return  void
 */
void task_brain_set_warn_code(uint8 code)
{
    osal_u8_msg_t *msgPtr = (osal_u8_msg_t*)osal_msg_allocate(sizeof(osal_u8_msg_t));
    
    if ( msgPtr == NULL )
    {
        BRAINLOG("faild");
        return;
    }
    
    msgPtr->hdr.event = APS_WARN_EVENT;
    msgPtr->byte = code;
    
    osal_msg_send(Brain_TaskID, (uint8 *)msgPtr);
}

// clear warn code
void task_brain_clear_warn_code(uint8 code)
{
    uint32 bit;
    
    if ( code > 31 ) 
    {
        BRAINLOG("OOR"); // out of range
        return;
    }
    
    if ( WARN_COD_CHGERR == code )
    {
        bit = 0x01 << WARN_COD_TEMPHIGH;
        bit |= 0x01 << WARN_COD_TEMPLOW;
        bit |= 0x01 << WARN_COD_CHGERR;
        
    }
    
    *d1_attr_state &= ~bit;
    
    // no warn state
    if ( *d1_attr_state == 0)osal_stop_timerEx(Brain_TaskID, TASK_BRAIN_EVT_WARN_LED);
    
}

// handle warn code
void task_brain_Handle_warning_code( uint8 code )
{
    uint32 bit;
//    uint32 time;
    BRAINLOG("[X]%d",code);
    
    if ( code > 31 ) 
    {
        BRAINLOG("OOR"); // out of range
        return;
    }
    
//    if ( code == WARN_COD_CELLTEMPLOW )
//    {
//        if ( hal_usb_insterd_check() )
//        {
//            code = WARN_COD_TEMPLOW;
//        }
//        else 
//        {
//            
//        }
//    }
    
    if ( code == WARN_COD_CHGERR )
    {
        if ( d1_attr_temp > 50 ) code = WARN_COD_TEMPHIGH;
        else if ( d1_attr_temp < 0 ) code = WARN_COD_TEMPLOW;
        else {
            
//            // long time , so protect?
//            if ( g32_usb_insert_time != U32_FF )
//            {
//                time = osal_getClock();
//                time -= g32_usb_insert_time;
//                // 9 hour
//                if ( time > (3600 * 9 ) ){
//                    code = WARN_COD_CHGTIMEOUT;
//                }
//            }
        }
    }
    
    bit = 0x01 << code;
    
    if ( *d1_attr_state & bit ){ 
        // this warn is exsit.
        return;
    }
    
    if ( *d1_attr_state == 0 ) 
    {
        // first warn code
        //osal_start_timerEx(Brain_TaskID,TASK_BRAIN_EVT_WARN_LED,10);
        osal_set_event(Brain_TaskID,TASK_BRAIN_EVT_WARN_LED);
    }
    
    *d1_attr_state  |= bit;
}

